-
-
Notifications
You must be signed in to change notification settings - Fork 243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add jwks parsing (abandoned) #112
Conversation
add jwks implementation to simple access to x5c to verify jwt
Wow! 🏆 super exciting to see this added, thank you so much for your contribution ❤️ This would be a start towards #94 which I think a lot of people would benefit from! There's a few key details missing in order for this to be merged
I very happy to see this PR get merged, let me know if you need more help! 🚀 |
example/jwks-verify.cpp
Outdated
auto verifier = jwt::verify() | ||
.allow_algorithm(jwt::algorithm::rs256(jwt::helper::convert_base64_der_to_pem(x5c), "", "", "")) | ||
.with_issuer(issuer) | ||
.leeway(10000000000UL); // value in seconds, add some to compensate timeout |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps, a simple token with no expiration is possible?
|
||
public: | ||
JWT_CLAIM_EXPLICIT jwks(const typename json_traits::string_type& jwks_token) { | ||
auto parse_claims = [](const typename json_traits::string_type& str) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this block seems to be copy pasted from the original
📓 for myself to look into a small refactor!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, and it costs an extra move, good point to refactor.
include/jwt-cpp/jwt.h
Outdated
}; | ||
|
||
template<typename json_traits> | ||
class jwks_keys { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this "parser" could be a static method that returns a vector, this was the implementation is not limited on KIDs being used in all the keys
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to_vector() is added
Co-authored-by: Chris Mc <[email protected]>
Co-authored-by: Chris Mc <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look really good! 👑
There's a few more details about x5c
handling I would appreciate your thoughts on.
Lastly, I need to get my note book and review them, I may come back with a suggestion to make the jwks
more generic... there's a lot of variety with the content and I want to make sure. Hopefully you can understand!
Keep up the awesome work 💪
|
||
/** | ||
* Get x5c claim | ||
* \return x5c as string | ||
* \throw std::runtime_error If claim was not present | ||
* \throw std::bad_cast Claim was present but not a string (Should not happen in a valid token) | ||
*/ | ||
typename json_traits::string_type get_x5c() const { return json_traits::as_string(get_jwks_claim("x5c").as_array().front()); } //do not use serialize() instead | ||
typename json_traits::string_type get_x5c() const { return json_traits::as_string(get_jwk_claim("x5c").as_array().front()); } //do not use serialize() instead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the consumer will/may need the array in larger systems as per the rfc 4.7
The PKIX certificate containing the key value MUST be the first
certificate. This MAY be followed by additional certificates, with
each subsequent certificate being the one used to certify the
previous one.
What do you think about having two functions?
typename json_traits::array_type get_x5c() const;
typename json_traits::string_type get_x5c_key_value() const;
Secondly, front
might be a little dangerous! Calling front on an empty container is undefined
please throw if empty 💥
include/jwt-cpp/jwt.h
Outdated
typename json_traits::string_type error_msg = "jwk with key id \""; | ||
error_msg += key_id; | ||
error_msg += "\" not found"; | ||
throw std::runtime_error(error_msg.c_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the caller knows the kid they passed, no need to repeat it
typename json_traits::string_type error_msg = "jwk with key id \""; | |
error_msg += key_id; | |
error_msg += "\" not found"; | |
throw std::runtime_error(error_msg.c_str()); | |
throw std::runtime_error("jwk with matching key id not found"); |
|
||
private: | ||
|
||
std::unordered_map<typename json_traits::string_type, jwks_t> jwks_keys_claims; | ||
std::unordered_map<typename json_traits::string_type, jwk_t> jwks_claims; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only because i've implemented this and used a few different auth servers... I am really unsure about this being a map...
What if there are two keys neither have KIDs? One would be lost, most likely the new key that is starting to issue tokens.
for (const auto& k : json_traits::as_object(val)) { | ||
size_t id = 0; | ||
for (const typename json_traits::value_type& item : json_traits::as_array(k.second)) { | ||
jwk_t jwk_entry(item); | ||
if (jwk_entry.has_key_id()) | ||
res.emplace(jwk_entry.get_key_id(), std::move(jwk_entry)); | ||
else | ||
res.emplace(std::to_string(id), std::move(jwk_entry)); | ||
++id; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, so I would really like if we could leave the KID outside of the JWKS logic because it's important to support workflows that do not required them.
I will come back with some changes against your branch, I think the biggest limitation is the parsing or "map of claims"
I also see we don't check "keys"
explicitly is the JWKS which would open use to a vulnerability
@dtiukalov please consider dtiukalov#1 |
This looks great! Basically this is exactly what I was looking for. A single nice c++ library to handle jwt auth including jwk handling. |
Sadly it seems OP has stopped working on this, it would be greatly appreciated if you could pick up and work on this! Lots of work has been done just needs a little push to get it over |
That is too bad. |
@prince-chrismc what's left in this PR? maybe i can take a shot at this |
I attempted to help the original author and made a PR against his branch.... https://github.com/prince-chrismc/jwt-cpp/tree/add-jwks is the latest code Sadly it's been a while and I do not recall the details... If you have time to push this feature I'd love to help! |
It will probably also need a pretty significant update to the current version. |
Does it make sense to start a new PR with OP's changes + @prince-chrismc 's suggestions to it, targetting the latest version? I think looking at the latest diff might help us see what's left |
add jwks implementation to simple access to x5c to verify jwt: